#include <iostream>

using std::cout;
using std::endl;

class Point
{
public:
    Point(int ix = 0, int iy = 0)
    : _ix(ix)
    , _iy(iy)
    {
        cout << "Point(int = 0, int = 0)" << endl;
    }

    //默认情况下，编译器会自动生成拷贝构造函数
    //1、拷贝构造函数参数中的引用符号可以去掉吗？
    //答案：不能去掉，如果去掉编译器会报错；如果去掉，那么
    //函数的参数就是类类型，如果在调用的时候，会满足拷贝
    //构造函数的调用时机2，会继续执行拷贝构造函数，以此类推
    //会一直执行拷贝构造函数,而函数的参数是会入栈，而栈是
    //有大小，那么一直调用下去会导致栈溢出
    //const Point rhs = pt


    //2、拷贝构造函数参数中const可以去掉吗?
    //答案：当传递的对象是右值的时候，非const左值引用不能
    //绑定到右值上，所以对于拷贝构造函数参数是右值的时候
    //就会报错，就不能去掉const
    Point(const Point &rhs)
    : _ix(rhs._ix)
    , _iy(rhs._iy)
    {
        cout << "Point(const Point &)" << endl;
    }

    void print()
    {
        cout << "(" << _ix
             << ", " << _iy
             << ")" << endl;
    }

    //默认情况下，编译器也会自动生成析构函数
    ~Point()
    {
        cout << "~Point()" << endl;
    }

private:
    int _ix;
    int _iy;
};

void test()
{
    Point pt(1, 2);
    cout <<"pt = ";
    pt.print();

    cout << endl;
    Point pt2 = pt;//会执行拷贝构造函数
    cout <<"pt2 = ";
    pt2.print();
}

void test2()
{
    //什么是左值，什么右值？
    //可以取地址的是左值，不能取地址是右值
    //右值包括：临时对象、临时变量、匿名变量、匿名对象、字面值
    //常量(10、20、1)
    int number = 10;
    int &ref = number;
    const int &ref3 = 10;//ok
    const int &ref4 = number;//ok
    /* int &ref2 = 10;//error,非const左值引用，不能绑定右值 */
    &number;
    /* &10;//error,右值，字面值常量 */

    //属于临时对象/匿名对象,它的生命周期比较短,只在本行，当
    //这一行执行结束之后会立马销毁。属于右值的一种
    /* Point(1, 2); */

    /* &Point(1, 2);//error,右值不能取地址 */
    //报错的显示：不能将非const的左值引用绑定到右值
    const Point &rhs = Point(1, 2);
    Point pt = Point(1, 2);
    cout << "pt = ";
    pt.print();
}

int main(int argc, char *argv[])
{
    test2();
    return 0;
}

